package org.acghub.demo.akka.helloworld;

import akka.Done;
import akka.actor.typed.ActorRef;
import akka.actor.typed.ActorSystem;
import akka.actor.typed.Behavior;
import akka.actor.typed.javadsl.AbstractBehavior;
import akka.actor.typed.javadsl.ActorContext;
import akka.actor.typed.javadsl.Behaviors;
import akka.actor.typed.javadsl.Receive;
import scala.Function1;
import scala.concurrent.Future;
import scala.util.Try;

import java.util.concurrent.TimeUnit;

/**
 * @author zhouhe
 */
public final class HelloWorldMain extends AbstractBehavior<HelloWorldMain.SayHello> {

    private final ActorRef<HelloWorld.Greet> greeter;

    private final ActorRef<HelloWorld.Greeted> greeted;

    private HelloWorldMain(ActorContext<SayHello> context) {
        super(context);
        greeter = context.spawn(HelloWorld.create(), "greeter");
        greeted = context.spawn(HelloWorldBot.create(3), "greeted");
    }

    public static Behavior<SayHello> create() {
        return Behaviors.setup(HelloWorldMain::new);
    }

    @Override
    public Receive<SayHello> createReceive() {
        return newReceiveBuilder().onMessage(SayHello.class, this::onSayHello).build();
    }

    private Behavior<SayHello> onSayHello(SayHello command) {
        greeter.tell(new HelloWorld.Greet(command.name, greeted));
        return this;
    }

    public record SayHello(String name) {
    }

    public static void main(String[] args) {
        ActorSystem<SayHello> system = ActorSystem.create(HelloWorldMain.create(), "hello");
        system.tell(new HelloWorldMain.SayHello("world"));
        try {
            TimeUnit.SECONDS.sleep(10);
        } catch (InterruptedException e){
            system.log().error("InterruptedException", e);
        }
        Future<Done> future = system.whenTerminated();
        future.onComplete(v1 -> {system.log().info("system terminated"); return null; }, system.executionContext());
        system.terminate();
    }
}